package com.pactera.madp.common.crypto.sm;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.util.HexUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;

import java.io.IOException;
import java.math.BigInteger;

public class SM2Utils {
    /**
     * 生成密钥对，公钥和私钥
     *
     * @return 密钥对
     */
    public static SM2Impl.SM2KeyPair createKeyPair() {
        return new SM2Impl().genKeyPair();
    }
    
    /**
     * 获取私钥（经过Base64转码过）
     *
     * @param keyPair 秘钥对
     * @return 被Base64转码加密过的私钥
     */
    public static String getPrivateKey(SM2Impl.SM2KeyPair keyPair) {
        if (null == keyPair) {
            return null;
        }
        BigInteger privateKeyInteger = keyPair.getPrivateKey();
        byte[] privateKeyBytes = SM2.bigInteger2Bytes(privateKeyInteger);
        return (null == privateKeyBytes ? null : Base64.encode(privateKeyBytes));
    }
    
    /**
     * 获取公钥（经过Base64转码加密过）
     *
     * @param keyPair 密钥对
     * @return 被Base64转码加密过的公钥
     */
    public static String getPublicKey(SM2Impl.SM2KeyPair keyPair) {
        if (null == keyPair) {
            return null;
        }
        byte[] publicKeyBytes = keyPair.getPublicKey().getEncoded();
        return (null == publicKeyBytes ? null : Base64.encode(publicKeyBytes));
    }

	/**
	 * 公钥加密
	 * @param data		待加密二进制内容
	 * @param publicKey	二级制公钥
	 * @return	加密后内容二进制
	 */
	public static byte[] encrypt(byte[] data, byte[] publicKey){
        return new SM2Impl().encrypt(data, publicKey);
    }

	/**
	 * 公钥加密
	 * @param data		待加密二进制内容
	 * @param publicKey	二级制公钥
	 * @return	加密后内容16进制字符串
	 */
	public static String encryptHex(byte[] data, byte[] publicKey){
    	return HexUtil.encodeHexStr(encrypt(data, publicKey));
	}

	/**
	 * 公钥加密
	 * @param data		待加密二进制内容
	 * @param publicKey	二级制公钥
	 * @return	加密后内容base64格式字符串
	 */
	public static String encryptBase64(byte[] data, byte[] publicKey){
		return Base64.encode(encrypt(data, publicKey));
	}

	/**
	 * 公钥加密
	 * @param data		待加密内容
	 * @param publicKey	公钥（16进制字符串或者base64格式字符串）
	 * @return	加密后内容16进制字符串
	 */
	public static String encryptHex(String data, String publicKey){
		return encryptHex(StrUtil.bytes(data), SecureUtil.decode(publicKey));
	}

	/**
	 * 公钥加密
	 * @param data		待加密内容
	 * @param publicKey	公钥（16进制字符串或者base64格式字符串）
	 * @return	加密后内容base64格式字符串
	 */
	public static String encryptBase64(String data, String publicKey){
		return encryptBase64(StrUtil.bytes(data), SecureUtil.decode(publicKey));
	}

	/**
	 * 私钥解密
	 * @param encryptedData	待解密内容[二进制]
	 * @param privateKey   私钥[二进制]
	 * @return	解密后内容二进制
	 */
    public static byte[] decrypt( byte[] encryptedData, byte[] privateKey){
        return new SM2Impl().decrypt(encryptedData, privateKey);
    }

	/**
	 * 私钥解密
	 * @param encryptedData	待解密内容[16进制或base64格式]
	 * @param privateKey   私钥[16进制或base64格式]
	 * @return	解密后内容二进制
	 */
	public static byte[] decrypt(String encryptedData, String privateKey){
		return decrypt(SecureUtil.decode(encryptedData), SecureUtil.decode(privateKey));
	}

	/**
	 * 私钥解密
	 * @param encryptedData	待解密内容[16进制或base64格式]
	 * @param privateKey   私钥[16进制或base64格式]
	 * @return	解密后内容字符串
	 */
	public static String decryptStr(String encryptedData, String privateKey){
		return new String(decrypt(encryptedData, privateKey));
	}
    
    public static byte[] sign(byte[] userId, byte[] privateKey, byte[] sourceData) throws IOException {
        return new SM2Impl().sign(userId, privateKey, sourceData);
    }
    
    public static boolean verifySign(byte[] userId, byte[] publicKey, byte[] sourceData, byte[] signData) throws IOException {
        return new SM2Impl().verifySign(userId, publicKey, sourceData, signData);
    }
}
